﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using Microsoft.Practices.Unity;
using WPFDBBrowser.Helpers;
using System.ComponentModel;
using System.Windows;

namespace WPFDBBrowser.Framework
{
    public class UserControlBase<TPresenter, TView> : UserControl
        where TPresenter : PresenterBase<TView>, new()
    {
        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="UserControlBase&lt;TPresenter, TView&gt;"/> class.
        /// </summary>
        public UserControlBase()
            : this(null)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UserControlBase&lt;TPresenter, TView&gt;"/> class.
        /// </summary>
        /// <param name="instanceName">Name of the instance.</param>
        public UserControlBase(string instanceName)
        {
            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                if (!(this is TView))
                    throw new InvalidCastException(
                        string.Format("Can't cast user control to {0}.", typeof(TView).FullName));
                this.Presenter = new TPresenter();
                this.Presenter.InstanceName = instanceName;
                this.Presenter.SetView(this);
                this.Loaded += new System.Windows.RoutedEventHandler(ControlLoaded);
            }
            this.OnBaseInitialized();
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets the parent window.
        /// </summary>
        /// <value>The parent window.</value>
        protected Window ParentWindow
        {
            get
            {
                return Window.GetWindow(this);
            }
        }
        protected TPresenter Presenter { get; set; }
        /// <summary>
        /// Gets or sets the name of the instance.
        /// </summary>
        /// <value>The name of the instance.</value>
        protected string InstanceName
        {
            get
            {
                if (this.Presenter != null)
                    return this.Presenter.InstanceName;
                return null;
            }
            set
            {
                if (this.Presenter != null)
                    this.Presenter.InstanceName = value;
            }
        }
        #endregion

        #region Virtual methods
        /// <summary>
        /// Called when control is loaded.
        /// </summary>
        protected virtual void OnControlLoaded()
        {
            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                this.RegisterCommands(this.ParentWindow);
            }
        }

        /// <summary>
        /// Registers the commands.
        /// </summary>
        /// <param name="window">The window.</param>
        protected virtual void RegisterCommands(Window window)
        {
        }

        /// <summary>
        /// Called when parent window is closed.
        /// This method can be used for disposing all components.
        /// </summary>
        protected virtual void OnParentWindowClosed()
        {
        }

        /// <summary>
        /// Called when base class is initialized.
        /// </summary>
        protected virtual void OnBaseInitialized()
        {
        }
        #endregion

        #region Private methods
        private void ControlLoaded(object sender, System.Windows.RoutedEventArgs e)
        {
            // Register closed event on window
            Window parent = Window.GetWindow(this);
            if (parent != null)
                parent.Closed += new EventHandler(parent_Closed);
            this.Presenter.OnViewLoaded();
            this.OnControlLoaded();
        }

        /// <summary>
        /// Handles the Closed event of the parent control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void parent_Closed(object sender, EventArgs e)
        {
            this.Presenter.OnViewClosed();
            this.OnParentWindowClosed();
        }
        #endregion
    }
}
